
void breakPoint(){}

void PANIC(char* why)
{
	printf("\nPANIC: %s\n", why);
	printf("primitiveIndex: %d  stack:\n", primitiveIndex);	

	int count=0;
	int context = activeContext;
	while(context != nil && count<20)
	{
		int home;
		if(classOf(context)==MethodContext) home = context;
		else if(classOf(context)==BlockContext) home = slotOf(context,6);
		int r = slotOf(home, 6);
		int method = slotOf(home, 4);
		
		printShortObject(r);
		printf(" %s\n", symbolToCString(methodSelector(method)));
		
		context = slotOf(context, 1);
		count++;
	}
	if(context != nil) printf("(...more...)\n");
	
#ifdef PROGRAM	
	breakPoint();
	while(1)
	{
		int a = *(int*)0; //cause a segfault so we can get a stack trace in gdb
		*(int*)0 = 50;
		//exit(1);
	}
#endif
#ifdef KERNEL
	exit(1);
#endif
}

void ASSERT(int cond, char* message)
{
	if( !cond ) PANIC(message);
}

int findSymbol(char* str)
{
	char *s2, *charstar;
	for(int object=heapStart;;)
	{
		int header = *(int*)object;
		switch(header&3){
			case 0: object+=8; break;
			case 1: object+=4; break;
			case 2:	if(object >= heapNext) PANIC("could not find symbol");
					else PANIC("unexpect free space in incrementOops");
			case 3: object+=0; break;
		}
		if(object >= heapNext) PANIC("went past end of heap");
			
		int format = formatOf(object);
		if(format >= 8 && format <= 11){ //8...11 - bytearrays and strings
			//if(classOf(object)==Symbol){
				int nWords = sizeOf(object);
				int nBytes= (nWords*4) - (format&3);
				
				if( nBytes != strlen(str) ) goto NextObject;
				
				charstar = (char*)(object+4);
				s2 = str;
				
				for(int j=0; j<nBytes && *s2 != '\0' ;j++)
				{
					if( *charstar != *s2 ) goto NextObject;
					charstar++;
					s2++;
				}
				if(*s2 == '\0') return object;	
			//}
		}
		NextObject:
		object+= (sizeOf(object)*4) + 4;
	}		
}

void printFullObject(int object)
{
	int header, htype, size, word, i;
	char byte;
	
	if( isSmInt(object) ) {
		printf("small int: %d\n", unpackSmInt(object));
		return;
	}
	
	header = *(int*)object;
	htype = header & 3;
	size = sizeOf(object);
	
	if(htype==2)//free space
		PANIC("attempting to print free space");
	if(htype==0) { //3-word header
		printf("%d\t%p extendedsize=%d-1\n", -2, *(int*)(object-8), *(int*)(object-8) >>2 );
	}
	if(htype==0 || htype==1){ //3-word or 2-word header
		printf("%d\t%p extendedclass=%p\n", -1, *(int*)(object-4), classOf(object));
	}
	
	printf("%d\t%p fmt=%d size=%d-1 cc=%d class=%s @%p\n", 
		0,
		header,
		(header >> 8) & 15,
		(header >> 2) & 0x3F,
		(header >> 12) & 0x1F,
		classNameOf(object),
		object);
	
	for(i=1; i<=size; i++){
		word = *((int*)(object+4*i));
		printf("%d\t%p ", i, word);
			byte = (word >> 0) & 0xFF;
			if(byte<33 || byte>126) byte = '.';
			printf("%c", byte);
			byte = (word >> 8) & 0xFF;
			if(byte<33 || byte>126) byte = '.';
			printf("%c", byte);
			byte = (word >> 16) & 0xFF;
			if(byte<33 || byte>126) byte = '.';
			printf("%c", byte);
			byte = (word >> 24) & 0xFF;
			if(byte<33 || byte>126) byte = '.';
			printf("%c", byte);
		
		printf(" ");
		printShortObject(word);
		printf("\n");
		
		if(i>20){ printf("(more...)\n"); break; }
	}
	//if( classOf(object)==Float ) printf("\t(%lf)\n", fromFloat(object));
}

void printShortObject(int oop)
{
	if(isSmInt(oop)) {
		printf("%d", unpackSmInt(oop));
	}else if(oop==true){
		printf("true");
	}else if(oop==false){
		printf("false");	
	}else if(oop==nil){
		printf("nil");
	}else if(classOf(oop)==Symbol){
		printf("#%s", symbolToCString(oop));
	}else if( isA(oop,String) ){
		printf("\'%s\'", symbolToCString(oop));
	}else{
		printf("a%s@%p", classNameOf(oop), oop);
	}
}

char* otherS = "???";
char* classNameOf(int object)
{
	if( sizeOf(classOf(object)) < 9 ){
	
		if( sizeOf(object) < 9 )
		{
			return otherS;
		}
		else
		{
			return strcat( symbolToCString(slotOf(object,9)), "class" );
		}
	}else{
		return symbolToCString(slotOf(classOf(object),9));
	}
}

char* outOfBoundsCString = "OUT-OF-BOUNDS";
char* notASymCString = "NOT-A-SYMBOL";
char reuseString[1000];
char* symbolToCString(int sym)
{
	int len, i;
	char *str;
	
	if( !objectInBounds(sym) ) return outOfBoundsCString;
	
	if( classOf(sym) != Symbol && !isA(sym,String) ) return notASymCString;
	
	len = sizeOf(sym) * 4 + 1;
	if(len>999) PANIC("reuseString overflow");
	str = (char*)reuseString;
	for(i=0; i<len-1; i++) str[i] = byteSlotOf(sym,i+1);
	str[len-1]=0;
	return str;
}

/*check that this oop is plausibly correct: that it is either a small integer or within the space of allocated objects and word-aligned*/
int objectInBounds(int object)
{
	if(object&1==1) return 1; //small integers are good;
	if(object%4!=0) return 0; // if not word aligned, bad
	return (object>=heapStart && object<=heapLimit); //if within object space, good
}

int printcode(unsigned char b){

	printf("<%d ", b);
		
	switch(b){
		
			// load receiver variable
			case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: 
            case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: 
                printf("push rcvr variable %d", (b&0xF)+1 ); break;
				
			// load temporary variable
			case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: 
            case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: 
                printf("push temp %d",(b&0xF)+1 ); break;

			// loadLiteral
			case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: 
            case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: 
            case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: 
            case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: 
                printf("push literal %d", (b&0x1F)+1 ); break;
				
			// loadLiteralIndirect
			case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: 
            case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: 
            case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: 
            case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95: 
                printf("push indirect literal %d", (b&0x1F)+1 ); break;
				
            case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: 
				printf("storeAndPop rcvr"); break;	
            case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111: 
				printf("storeAndPop temp %d",(b&7)+1); break;
		
		case 112: printf("push self"); break;
		case 113: printf("push true"); break;
		case 114: printf("push false"); break;
		case 115: printf("push nil"); break;
		case 116: printf("push -1"); break;
		case 117: printf("push 0"); break;
		case 118: printf("push 1"); break;
		case 119: printf("push 2"); break;
		
		case 120: printf("return self"); break;
		case 121: printf("return true"); break;
		case 122: printf("return false"); break;
		case 123: printf("return nil"); break;
		case 124: printf("return top"); break;
		case 125: printf("block return top"); break;
		
		case 135: printf("pop"); break;
		case 136: printf("push top"); break;
		case 137: printf("push thisContext"); break;
		
		case 152: printf("jump if false by 1"); break;
		case 153: printf("jump if false by 2"); break;
		case 154: printf("jump if false by 3"); break;
		case 155: printf("jump if false by 4"); break;
		case 156: printf("jump if false by 5"); break;
		case 157: printf("jump if false by 6"); break;
		case 158: printf("jump if false by 7"); break;
		case 159: printf("jump if false by 8"); break;
		
        case 168: case 169: case 170: case 171:	printf("long if true jump"); break;
        case 172: case 173: case 174: case 175: printf("long if false jump"); break;
		
		case 176: printf("send +"); break;
		case 177: printf("send -"); break;
		case 178: printf("send <"); break;
		case 179: printf("send >"); break;
		case 180: printf("send <="); break;
		case 181: printf("send >="); break;
		case 182: printf("send =="); break;
		case 183: printf("send !="); break;
		case 184: printf("send *"); break;
		case 185: printf("send /"); break;
		case 186: printf("send \\\\"); break;
		case 187: printf("send @"); break;
		case 188: printf("send bitShift:"); break;
		case 189: printf("send //"); break;
		case 190: printf("send bitAnd:"); break;
		case 191: printf("send bitOr:"); break;
		
		case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: 
        case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: 
                printf("other quick send");
				break;	
		
		case 208: case 209: case 210: case 211: case 212: case 213:	case 214: case 215:
		case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223:
				printf("send 0-arg literal %d",(b&0xF));
				break;
		case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231:
		case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239:	
				printf("send 1-arg literal %d",(b&0xF));
				break;
        case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: 
        case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255:
				printf("send 2-arg literal %d",(b&0xF));
				break;				
		default: printf("unknown", b);
	}
	printf(">\n");
	return b;
}
